#include <iostream>
#include <unistd.h>
#include <vector>
#include <functional>
#include <string>
#include "task.hpp"
using work_t = std::function<void()>;
enum
{
    OK = 0,
    USAGEERROR,
    PIPEERROR,
    FORKERROR
};
class Channel
{
public:
    Channel(int wfd, pid_t id)
        : _wfd(wfd), _who(id)
    {
        _name = "channel-" + std::to_string(wfd) + "-" + std::to_string(id);
    }
    std::string Name()
    {
        return _name;
    }
    void Send(int cmd)
    {
        ::write(_wfd,&cmd,sizeof(cmd));
    }
    ~Channel()
    {
    }

private:
    int _wfd;
    std::string _name;
    pid_t _who;
};
void Usage(std::string proc)
{
    std::cout << "Usage: " << proc << "process-num" << std::endl;
}
void Worker()
{
    while(true)
    {
        int cmd=0;
        int n=::read(0,&cmd,sizeof(cmd));
        if(n==sizeof(cmd))
        {
            tm.Excute(cmd);
        }else if(n==0)
        {}
        else
        {}
    }
}
int Initprocesspool(const int &processnum, std::vector<Channel> &channels, work_t work)
{
    // 创建指定个数的进程
    for (int i = 0; i < processnum; i++)
    {
        // 先有管道
        int pipefd[2] = {0};
        int n = pipe(pipefd);
        if (n < 0)
            return FORKERROR; // 管道创建失败，退出码问2
        pid_t id = ::fork();  // 创建子进程
        if (id == 0)
        {
            // 子进程
            ::close(pipefd[1]);   // read
            ::dup2(pipefd[0], 0); // 重定向，从标准输入中读数据stdout，这样不需要传参数，与work解耦
            work();               // 工作完成就退出
            exit(0);
        }
        // 父进程
        else if (id > 0)
        {
            ::close(pipefd[0]); // write
            channels.emplace_back(pipefd[1], id);
        }
    }
    return OK;
}
void DebugPrint(std::vector<Channel> &channels)
{
    for (auto &c : channels)
    {
        std::cout << c.Name() << std::endl;
    }
}
int main(int argc, char *argv[])
{
    if (argc != 2) // 命令行格式输入错误
    {
        Usage(argv[0]);
        return USAGEERROR;
    }
    int num = std::stoi(argv[1]);

    std::vector<Channel> channels;
    // 1.初始化子进程
    Initprocesspool(num, channels, Worker);
    // 打印channel
    // DebugPrint(channels);
    // 2.派发任务 轮询
    int who=0;
    while(true)
    {
        //1.选择一个任务
        int task=tm.SelectTask();
        //2.选择一个子进程channel
        Channel& curr=channels[who++];
        who%=channels.size();
        std::cout<<"#######################"<<std::endl;
        std::cout<<"send:"<<task<<" to "<<curr.Name()<<std::endl;
        std::cout<<"#######################"<<std::endl;
        //3.派发任务
        curr.Send(task);
        sleep(2);
    }
    sleep(100);
    return 0;
}